﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace CPAIS.Updater
{
    /// <summary>
    /// Represents an abstract updater for updating progress degree.
    /// </summary>
    /// <exception cref="CancelUpdatingException">Thrown when cancelling updating</exception>
    /// <exception cref="ArgumentOutOfRangeException">Throw when set invalid updating step</exception>
    public abstract class ProgressUpdater : StateUpdater
    {
        #region Variables in ProgressUpdater
        private double step;
        private double progress;
        #endregion

        /// <summary>
        /// Constructor with updating step, default is 0.01 (1%).
        /// </summary>
        /// <param name="step">Progress step for updating</param>
        /// <exception cref="ArgumentOutOfRangeException">Throw when set invalid updating step</exception>
        public ProgressUpdater(double step = 0.01)
        {
            Step = step;
            progress = 0;
        }

        /// <summary>
        /// Gets and sets updating step.
        /// </summary>
        /// <exception cref="ArgumentOutOfRangeException">Throw when set invalid updating step</exception>
        public double Step
        {
            get { return step; }
            set
            {
                if (value > 0.001 && value < 0.2)
                    step = value;
                else
                    throw new ArgumentOutOfRangeException("step", "Update step should between 0.001 and 0.2");
            }
        }

        /// <summary>
        /// Gets updating progress.
        /// </summary>
        public double Progress
        {
            get { return progress; }
        }

        /// <summary>
        /// Override StateUpdater.OnUpdateMessage
        /// </summary>
        protected override bool OnUpdateMessage(string message)
        {
            return true;
        }

        /// <summary>
        /// Override Updater.OnComplete
        /// </summary>
        protected override void OnComplete()
        {
            progress = 1.0;
            base.OnComplete();
        }
        
        /// <summary>
        /// Updates progress.
        /// </summary>
        /// <param name="progress">Progress</param>
        /// <exception cref="CancelUpdatingException">Thrown when cancelling updating</exception>
        public void UpdateProgress(double progress)
        {
            if (State == UpdateState.Updating && Math.Abs(progress - this.progress) > step)
            {
                this.progress = progress;
                if (!OnUpdateProgress(progress))
                {
                    Cancel();
                }
            }
        }
        protected abstract bool OnUpdateProgress(double progress);
    }
}
